iT邦幫忙

2023 iThome 鐵人賽

DAY 17
0
Vue.js

Nuxt 3 初學者指南:30天從基礎到實踐系列 第 17

Day 17 – Nuxt 3 State Management

  • 分享至 

  • xImage
  •  

Nuxt 3 提供一個 composable useState 用來建立元件間的共用響應式狀態,可以當成是 SSR 友善的 ref,其值會在 SSR 之後保留並在所有元件中共享。

使用方式

修改 app.vue

// app.vue
<template>
  <NuxtPage />
</template>

修改 pages/index.vue

// index.vue
<template>
  <NuxtLink to="counter">counter</NuxtLink>
  <br/>
  <NuxtLink to="counter2">counter2</NuxtLink>
</template>

pages/ 新增 counter.vue

// pages/counter.vue
<template>
  <div>
    Counter: {{ counter }}
    <button @click="counter++">
      +
    </button>
    <button @click="counter--">
      -
    </button>
  </div>
</template>

<script setup lang="ts">
  const counter = useState('counter', () => Math.round(Math.random() * 1000))
</script>

pages/ 新增 counter2.vue

// pages/counter2.vue
<template>
  <div>
    Counter: {{ counter }}
    <button @click="counter++">
      +
    </button>
    <button @click="counter--">
      -
    </button>
  </div>
</template>

<script setup lang="ts">
  const counter = useState('counter', () => Math.round(Math.random() * 1000))
</script>

結果如下方影片,我們用 useState 建立一個響應式狀態 counter,當第一次進入 counter.vue 時會初始化狀態並給一個隨機值,不管增加或減少 counter 的值都會被紀錄下來,而當我們跳轉到 counter2.vue 時因為我們一樣使用了 useState('counter') 所以就會把剛剛已經建立的 counter 拿出來用,而且值也會一樣,這就是 Nuxt 3 的共用響應式狀態。

雖然這樣寫法可以達到共用響應式狀態的目的,但實際在開發上如果這樣寫很不好管理,因為散落在各個檔案裡根本不知道到底建立了哪一些共用響應式狀態,可能會發生在其他頁面已經建立過一樣的名稱但是沒發現導致一直找不到 bug 的情況,所以我們會把共用響應式狀態統一寫在 composables

composables 裡新增 states.ts

// composables/states.ts
export const useCounter = () => useState('counter', () => Math.round(Math.random() * 1000))

修改 pages/counter.vuepages/counter2.vue

// pages/counter.vue & pages/counter2.vue
<template>
  <div>
    Counter: {{ counter }}
    <button @click="counter++">
      +
    </button>
    <button @click="counter--">
      -
    </button>
  </div>
</template>

<script setup lang="ts">
  const counter = useCounter()
</script>

結果如下,一樣能達到共用的目的,透過組合式函數的自動載入功能讓我們能少寫很多令人煩躁的程式碼,同時在開發時也能更容易管理共用響應式狀態。

為什麼不能直接用 ref

前面有提到 useState 是 SSR 友善的 ref,那如果直接使用 ref 會發生什麼事呢?

修改 composables/states.ts

// composables/states.ts
...
export const refCounter = ref(Math.round(Math.random() * 1000))

修改 pages/counter.vue

<template>
  <div>
    Counter: {{ counter }}
    <button @click="counter++">
      +
    </button>
    <button @click="counter--">
      -
    </button>
  </div>
</template>

<script setup lang="ts">
  const counter = refCounter
</script>

結果如下圖,當我們重新整理的時候會發現畫面上的數字跳了兩次,這是因為 Nuxt 3 的 Universal Rendering 是 SSR + CSR(在 Day 2 – Nuxt 3 核心功能概念(上)有介紹過),所以會在 SSR 時渲染產生一次 refCounter,之後又在 CSR 時產生一次 refCounter,而為了避免這個現象才需要用 useState

🌞 Upcoming

到今天 Nuxt 3 的核心功能概念都介紹差不多了,明天開始會介紹一些 Nuxt 3 好用的 Modules,讓開發更迅速。


參考資料:

State Management


上一篇
Day 16 – Nuxt 3 Transitions
下一篇
Day 18 – Nuxt DevTools(一)
系列文
Nuxt 3 初學者指南:30天從基礎到實踐30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言